﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;

namespace Dummy.Web
{
    public class GameData
    {
        static ManualResetEvent _readWriteFlag = new ManualResetEvent(true);
        static Dictionary<string, GameDataGamer> _gamers = new Dictionary<string, GameDataGamer>();

        public static void InitGameData()
        {
            DictionaryRus.Init();
        }

        static void enterFlag()
        {
            _readWriteFlag.WaitOne();
            _readWriteFlag.Reset();
        }

        static bool exitFlag(bool result)
        {
            _readWriteFlag.Set();
            return result;
        }

        static void exitFlag()
        {
            _readWriteFlag.Set();
        }

        public static bool ConnectGamer(string gamerName, GameClientCallback callback)
        {
            enterFlag();
            if (GamerExists(gamerName))
            {
                callback(GameClientCommand.gamerconnecterror, "gamer with given name is already on server");
                return exitFlag(false);
            }
            _gamers.Add(gamerName, new GameDataGamer(gamerName, callback));
            callback(GameClientCommand.gamerconnected, gamerName);
            SendBroadcastMessageGamerConnected(gamerName);
            return exitFlag(true);
        }

        private static void SendBroadcastMessageGamerConnected(string newGamerName)
        {
            foreach (string gamername in _gamers.Keys)
                if (gamername.ToLower() != newGamerName)
                    _gamers[gamername].callback(GameClientCommand.newgamercome, newGamerName);
        }

        static bool GamerExists(string gamerName)
        {
            return _gamers.ContainsKey(gamerName);
        }

        public static bool GetGamerList(GameClientCallback callback, string gamerName)
        {
            enterFlag();
            List<string> _gamerNameList = new List<string>();
            foreach (string gm in _gamers.Keys)
                if (gm.ToLower() != gamerName.ToLower())
                    _gamerNameList.Add(gm);
            callback(GameClientCommand.gamerlist, GameClient.GetCallbackParameter(_gamerNameList.ToArray()));
            return exitFlag(true);
        }

        public static bool SendInvite(string gamerName, string toGamerName)
        {
            enterFlag();

            GameDataGamer gamer1 = _gamers[gamerName];
            if (!GamerExists(toGamerName))
            {
                gamer1.callback(GameClientCommand.sendinviteerror, toGamerName, "Gamer doesn't exist");
                return exitFlag(false);
            }

            GameDataGamer gamer2 = _gamers[toGamerName];
            if (gamer2.isPlaying)
            {
                gamer1.callback(GameClientCommand.sendinviteerror, gamer2.gamerName, "Gamer is already playing");
                return exitFlag(false);
            }
            gamer2.callback(GameClientCommand.getinvite, gamer1.gamerName);

            return exitFlag(true);
        }

        public static bool StartGame(string gamerName, string competitorGamerName)
        {
            enterFlag();

            if (!GamerExists(competitorGamerName))
            {
                GameDataGamer gamer = _gamers[gamerName];
                gamer.callback(GameClientCommand.startgameerror, competitorGamerName, "Gamer doesn't exist");
                return exitFlag(false);
            }
            GameDataGamer gamer1 = _gamers[gamerName];
            GameDataGamer gamer2 = _gamers[competitorGamerName];
            if (gamer2.isPlaying)
            {
                gamer1.callback(GameClientCommand.startgameerror, competitorGamerName, "Gamer is playing now");
                return exitFlag(false);
            }

            string startWord = getRandomStartWord();
            gamer1.StartGame(competitorGamerName, true, startWord);
            gamer1.callback(GameClientCommand.startgame, competitorGamerName, "true", startWord);
            gamer2.StartGame(gamerName, false, startWord);
            gamer2.callback(GameClientCommand.startgame, gamerName, "false", startWord);

            return exitFlag(true);
        }

        static string getRandomStartWord()
        {
            return "балда"; //debug
            //return "balda";
        }

        public static void GamerMakeMove(string gamerName, int moveI, int moveJ, string IJchar, string word)
        {
            enterFlag();

            GameDataGamer gamer1 = _gamers[gamerName];
            GameDataGamer gamer2 = _gamers[gamer1.gamerCompetitorName];

            if (!DictionaryRus.WordExists(word))
            {
                gamer1.callback(GameClientCommand.gamermakemoveerror, string.Format("there is no word '{0}'", word));
                exitFlag();
                return;
            }
            if (gamer1.IsWordInYourWords(word))
            {
                gamer1.callback(GameClientCommand.gamermakemoveerror, string.Format("word '{0}' is already in your words", word));
                exitFlag();
                return;
            }
            if (gamer2.IsWordInYourWords(word))
            {
                gamer1.callback(GameClientCommand.gamermakemoveerror, string.Format("word '{0}' is already in competitor's words", word));
                exitFlag();
                return;
            }
            
            gamer1.MakeMove(word);
            gamer2.TakeMove();
            gamer1.callback(GameClientCommand.gamermakemove, "true", moveI.ToString(), moveJ.ToString(), IJchar, word, 
                gamer1.score.ToString(), gamer2.score.ToString());
            gamer2.callback(GameClientCommand.gamermakemove, "false", moveI.ToString(), moveJ.ToString(), IJchar, word, 
                gamer2.score.ToString(), gamer1.score.ToString());

            exitFlag();
        }
    }

    public enum GameClientCommand
    {
        error,
        gamerconnected,
        gamerconnecterror,
        gamerlist,
        sendinviteerror,
        getinvite,
        startgame,
        startgameerror,
        newgamercome,
        gamewordlist,
        gamermakemove,
        gamermakemoveerror
    }
}